# Copyright 2010 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Author: tu@tulrich.com (Thatcher Ulrich)

"""Update statistics based on new data.
"""


import datetime
import os
from google.appengine.api import users
from google.appengine.ext import db
import distro
import analysis


class Processor(db.Expando):
  tag = db.StringProperty()
  last_processed = db.DateTimeProperty()
  metrics = db.StringListProperty()
  # distro_<num> == float array for matching metric


def to_tagdata(processor):
  """Return a dict of { metric: distro } pairs.
  """
  metrics = processor.metrics
  out = {}
  for i in range(0, len(metrics)):
    metric = metrics[i]
    d = distro.Distro()
    if hasattr(processor, "distro_" + str(i)):
      d.deserialize(getattr(processor, "distro_" + str(i)))
    out[metric] = d
  return out
    

def from_tagdata(processor, tagdata):
  """Fill our values with the given { metric: distro } pairs from tagdata.
  """
  # Remove all the distros
  for k in processor.dynamic_properties():
    delattr(processor, k)

  # Re-insert the distros.
  processor.metrics = tagdata.keys()
  for i in range(0, len(processor.metrics)):
    metric = processor.metrics[i]
    d = tagdata[metric]
    setattr(processor, "distro_" + str(i), d.serialize())

    
def handler(app):
  """
  """
  #if not users.is_current_user_admin():
  #  app.response.out.write('admin only | <a href="%s">login</a>' %
  #                         users.create_login_url(app.request.uri))
  #  return

  # Pick a processor.  Find the least-recently updated one.
  q = db.GqlQuery("SELECT * FROM Processor ORDER BY last_processed ASC LIMIT 1")
  processors = q.fetch(1)
  processor = None
  if len(processors) == 0:
    # Create a default processor.
    processor = Processor()
    processor.tag = "all"
    processor.last_processed = datetime.datetime.utcfromtimestamp(0)
  else:
    processor = processors[0]
  
  # Update this processor.
  tagsets = {}
  tagdata = to_tagdata(processor)
  tagsets[processor.tag] = tagdata
  previous_last_processed = processor.last_processed
  last_processed = analysis.update_tagsets(tagsets, processor.last_processed)
  processor.last_processed = last_processed
  from_tagdata(processor, tagdata)
  db.put(processor)

  app.response.out.write("processed tag='%s', records from %s to %s<br/><hr/>\n" % (
      processor.tag,
      previous_last_processed.isoformat(' '),
      last_processed.isoformat(' ')))

  #app.response.out.write(analysis.dump_tagsets(tagsets))


def create_processor_handler(app):
  """
  """
  if not users.is_current_user_admin():
    app.response.out.write('admin only | <a href="%s">login</a>' %
                           users.create_login_url(app.request.uri))
    return

  tag = app.request.get("tag")
  if not tag:
    app.response.out.write("FAIL: empty tag")
    return

  q = db.GqlQuery("SELECT * FROM Processor WHERE tag = :1 LIMIT 1", tag)
  processors = q.fetch(1)
  if len(processors) > 0:
    app.response.out.write("Resetting %s<br/>\n" % tag)
    for p in processors:
      p.delete()

  processor = Processor()
  processor.tag = tag
  processor.last_processed = datetime.datetime.utcfromtimestamp(0)
  db.put(processor)

  app.response.out.write("OK")

    

